#include "stdafx.h"
#include "ring.h"

int ring::_thread_index = 0;

#define _thread_state	_states[_thread_index]

//---------------------------------------------------------------------------
void ring::pre(void)
{
	// make thread active
	_thread_state = ring_state::active;

	// assign thread to group
	_thread_state = _ring_group;

	if(_thread_state != ring_state::active_group_0 && _thread_state != ring_state::active_group_1)
	{
		throw std::exception("internal error - invalid ring group");
	}

	for(int i = 0; i < (int)_states.size() ; i++)
	{
		if(i == _thread_index)
		{
			continue;
		}

		// if my group's turn arrive - go right in!
		if(_thread_state != _ring_group)
		{
			break;
		}

		// if other thread is active, wait until is has a group
		while(_states[i] == ring_state::active)
		{
			::Sleep(10);
		}

		// if other thread is in the other group (that is not waiting)
		// wait until done OR my group's turn
		if(_states[i] == (ring_state)(1 - ((byte)(_thread_state))))
		{
			while(_states[i] == (ring_state)(1 - ((byte)(_thread_state))) && _thread_state == _ring_group)
			{
				::Sleep(10);
			}
		}
	}
}
//---------------------------------------------------------------------------
void ring::post(void)
{
	if(_thread_state != ring_state::active_group_0 && _thread_state != ring_state::active_group_1)
	{
		throw std::exception("internal error - invalid thread_state");
	}

	// switch the groups
	_ring_group = (ring_state)(1 - (byte)_thread_state);

	// make thread inactive
	_thread_state = ring_state::inactive;
}
//---------------------------------------------------------------------------
void ring::register_to_ring()
{
	std::unique_lock<std::mutex> ul(_registration_lock);

	ring_state state = ring_state::inactive;
	_states.push_back(state);

	_thread_index = (int)(_states.size() - 1); // give the thread its index in the vector
}
//---------------------------------------------------------------------------